package com.usian.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.usian.admin.feign.ArticleFeign;
import com.usian.admin.feign.WemediaFeign;
import com.usian.admin.service.AdChannelService;
import com.usian.admin.service.AdSensitiveService;
import com.usian.admin.service.WemediaNewsAutoScanService;
import com.usian.common.aliyun.GreeTextScan;
import com.usian.common.aliyun.GreenImageScan;
import com.usian.common.fastdfs.FastDFSClient;
import com.usian.common.wemedia.WemediaContants;
import com.usian.model.admin.pojos.AdChannel;
import com.usian.model.article.pojos.ApArticle;
import com.usian.model.article.pojos.ApArticleConfig;
import com.usian.model.article.pojos.ApArticleContent;
import com.usian.model.article.pojos.ApAuthor;
import com.usian.model.common.constants.AdminConstants;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmUser;
import com.usian.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Log4j2
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    private AdSensitiveService adSensitiveServiceI;

    @Autowired
    private WemediaFeign wemediaFeign;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private GreeTextScan greeTextScan;

    @Value("${fastdfs.url}")
    private String fastServiceUrl;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private AdChannelService adChannelServiceI;

    /**
      * 功能描述：文章审核的接口实现
      * @param: 文章id
      * @return：
      * @auther：
      */
    @Override
    @GlobalTransactional // 开启分布式事务
    public void autoScanByMediaNewsId(Integer id) {
        if (null == id) {
            log.error("传递的id为null");
            return;
        }
        //  1.根据id查询自媒体文章信息
        WmNews wmNews = wemediaFeign.findNewsById(id);
        if (null == wmNews) {
            log.error("自媒体文章为空，id为{}", id);
            return;
        }
        //  2. 文章状态为4（人工审核通过） 直接保存数据和创建索引
        if (WmNews.Status.ADMIN_SUCCESS.getCode() == wmNews.getStatus().shortValue()) {
            // 保存文章数据和创建索引
            saveApArticle(wmNews);
            return;
        }
        //  3.文章状态为8 发布时间<=当前时间 直接保存数据和创建索引
        if (WmNews.Status.SUCCESS.getCode() == wmNews.getStatus().shortValue()&&
                wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            // 保存文章数据和创建索引
            // 发布文章
            saveApArticle(wmNews);
            return;
        }
        //  4.文章状态为1，待审核
        if (WmNews.Status.SUBMIT.getCode() == wmNews.getStatus().shortValue()) {
            //  4.1.提取文本和图片
            Map<String, Object> textAndImageMap =  handleTextAndImage(wmNews);
            //  4.2.调用阿里云文本反垃圾审核
            //  wmNews.getContent()中的text内容
            boolean textScanResult =
                    handleTextInAliyun((String)textAndImageMap.get(AdminConstants.CONTENT_TEXT), wmNews);
            if (!textScanResult) return;
            //  4.3.调用阿里云图片审核服务
            //  wmNews.getContent()中的image内容+wmNews.getImages()(封面图片)
            boolean imageScanResult =
                    handleImageScanInAliyun((List<String>)textAndImageMap.get(AdminConstants.CONTENT_IMAGES), wmNews);
            if (!imageScanResult) return;
            //  4.4.文章内容是否包含了自管理的敏感词
            boolean textSensitiveResult =
                    handleTextSensitiveScan((String)textAndImageMap.get(AdminConstants.CONTENT_TEXT), wmNews);
            if (!textSensitiveResult) return;
            //  4.5.发布时间大于当前时间，修改文章状态为8(审核通过，待发布)
            if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                updateWmNews(wmNews, WmNews.Status.SUCCESS.getCode(), "内容审核通过，待发布");
                return;
            }
            //  4.6.审核通过，修改自媒体文章状态为9

            //  4.7.保存文章数据和创建索引(发布文章)
            saveApArticle(wmNews);
        }
    }

    @Override
    @GlobalTransactional
    public void releaseNews(WmNews wmNews) {
        if (null == wmNews) {
            log.error("自媒体文章为空");
            return;
        }
        //  文章状态为8 发布时间<=当前时间 直接保存数据和创建索引
        if (WmNews.Status.SUCCESS.getCode() == wmNews.getStatus().shortValue() &&
                wmNews.getPublishTime().getTime() <= System.currentTimeMillis()) {
            // 发布文章
            saveApArticle(wmNews);
            return;
        }

    }

    /**
     * 功能描述：自管理的敏感词检测
     * @param:  需要检测的内容文本
     * @return：
     * @auther：
     */
    private boolean handleTextSensitiveScan(String text, WmNews wmNews) {
        boolean flag = true;
        if (StringUtils.isBlank(text)){
            return flag;
        }
        // 1.取出自管理的敏感词库
        List<String> sensitives = adSensitiveServiceI.findAllSensitives();
        // 2.使用工具类进行检测
        SensitiveWordUtil.initMap(sensitives);

        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(text);
        if (resultMap.size() > 0) {
            flag = false;
            updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "内容文本包含敏感词");
        }
        return flag;
    }

    /**
      * 功能描述：阿里云图片检测
      * @param:  需要进行检测的图片合集
      * @return：
      * @auther：
      */
    private boolean handleImageScanInAliyun(List<String> imageList, WmNews wmNews) {
        boolean flag = true;
        if (imageList == null || imageList.isEmpty()) {
            return flag;
        }
        // 1.把图片从fastDFS下载出来
        try {
            List<byte[]> imageByteList = new ArrayList<>();
            for (String image : imageList) {
                String fileId = image.replace(fastServiceUrl, "");
                String groupName = fileId.substring(0, fileId.indexOf("/"));
                String imagePath = fileId.substring(fileId.indexOf("/") + 1);
                // group1/M00/00/00/rBENvl05FnaAM6J1AAaGax3lKLo443.jpg
                byte[] imageByte = fastDFSClient.download(groupName, imagePath);
                imageByteList.add(imageByte);
            }
            // 2.进行阿里云图片检测
            Map map = greenImageScan.imageScan(imageByteList);
            String suggestion = (String)map.get("suggestion");
            // pass 通过
            // block 屏蔽
            // review 建议进一步人工审核
            if (!suggestion.equals("pass")) {
                // block，审核状态变更成2，原因是内容违规
                if (suggestion.equals("block")) {
                    //
                    updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "图片存在违规信息");
                    flag = false;
                }
                // review，审核状态变更成3，原因是内容可能存在违规信息
                if (suggestion.equals("review")) {
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "图片可能存在违规信息，需要进一步人工审核");
                    flag = false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }


    /**
     * 功能描述：更新文章的状态和审核原因
     * @param:
     * @return：
     * @auther：
     */
    private void updateWmNews(WmNews wmNews, Short status, String reason){
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wemediaFeign.updateNewsStatus(wmNews);
    }

    /**
     * 功能描述：阿里云文本检测功能
     * @param:
     * @return：
     * @auther：
     */
    private boolean handleTextInAliyun(String text, WmNews wmNews) {
        boolean flag = true;
        if (StringUtils.isBlank(text)){
            return flag;
        }
        try {
            Map map = greeTextScan.greeTextScan(text);
            String suggestion = (String)map.get("suggestion");
            // pass
            // block
            // review
            if (!suggestion.equals("pass")) {
                // block，审核状态变更成2，原因是内容违规
                if (suggestion.equals("block")) {
                    //
                    updateWmNews(wmNews, WmNews.Status.FAIL.getCode(), "内容存在违规信息");
                    flag = false;
                }
                // review，审核状态变更成3，原因是内容可能存在违规信息
                if (suggestion.equals("review")) {
                    updateWmNews(wmNews, WmNews.Status.ADMIN_AUTH.getCode(), "内容可能存在违规信息，需要进一步人工审核");
                    flag = false;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文本审核出现异常，信息如下:{}", e.getMessage());
            flag = false;
        }
        return flag;
    }

    /**
      * 功能描述：提取自媒体文章的文本和图片，用于后续的文本和图片检测
      * @param:
      * @return：
      * @auther：
      */
    private Map<String, Object> handleTextAndImage(WmNews wmNews) {
        String content = wmNews.getContent();
        Map<String, Object> resultMap = new HashMap<>();
        StringBuilder textSb = new StringBuilder();
        List<String> imageList = new ArrayList<>();
        // 提取
        // 提取content里面的文本和图片
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if (map.get(AdminConstants.CONTENT_TYPE).equals(AdminConstants.CONTENT_TEXT)) {
                textSb.append(map.get(AdminConstants.CONTENT_VALUE));
            } else if (map.get(AdminConstants.CONTENT_TYPE).equals(AdminConstants.CONTENT_IMAGE)) {
                imageList.add((String)map.get(AdminConstants.CONTENT_VALUE));
            }
        }
        // 提取封面的图片
        // 封面图片不为空并且不是无图文章，多张图片是用逗号分割开
        if (StringUtils.isNotBlank(wmNews.getImages()) &&
                wmNews.getType().shortValue() != WemediaContants.WM_NEWS_NONE_IMAGE.shortValue()) {
            String[] sp = wmNews.getImages().split(",");
            imageList.addAll(Arrays.asList(sp));
        }
        resultMap.put(AdminConstants.CONTENT_TEXT, textSb.toString());
        resultMap.put(AdminConstants.CONTENT_IMAGES, imageList);
        return resultMap;
    }

    /**
      * 功能描述：文章发布/保存文章相关信息和创建ES索引库
      * @param:
      * @return：
      * @auther：
      */
    private void saveApArticle(WmNews wmNews){
        // 1.保存文章相关信息
        // 1.1.同步 ap_article
        ApArticle apArticle = saveArticle(wmNews);
        // 1.2.同步 ap_article_config
        saveApArticleConfig(apArticle.getId());
        // 1.3.同步 ap_article_content
        saveApArticleContent(apArticle.getId(), wmNews.getContent());
        // 2.创建ES索引库  TODO
        // 3.变更WmNews的状态为9(已发布)
        wmNews.setArticleId(apArticle.getId());
        updateWmNews(wmNews, WmNews.Status.PUBLISHED.getCode(), "文章审核通过，已发布");
    }

    /**
     * 功能描述：同步ap_article_content
     * @param: articleId:文章id  content:文章内容
     * @return：
     * @auther：
     */
    private void saveApArticleContent(Long articleId, String content) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(articleId);
        apArticleContent.setContent(content);
        articleFeign.saveArticleContent(apArticleContent);
    }

    /**
     * 功能描述：同步 ap_article_config
     * @param: 文章id
     * @return：
     * @auther：
     */
    private void saveApArticleConfig(Long articleId) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(articleId);
        apArticleConfig.setIsComment(true);
        apArticleConfig.setIsDelete(false);
        apArticleConfig.setIsDown(false);
        apArticleConfig.setIsForward(true);
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    /**
     * 功能描述：保存ap_article
     * @param:
     * @return：
     * @auther：
     */
    private ApArticle saveArticle(WmNews wmNews) {
        ApArticle apArticle = new ApArticle();
        // 赋值
        apArticle.setTitle(wmNews.getTitle());
        WmUser wmUser = wemediaFeign.findUserById(wmNews.getUserId());
        ApAuthor apAuthor = articleFeign.findByName(wmUser.getName());
        if (apAuthor != null) {
            apArticle.setAuthorId(apAuthor.getId().longValue());
            apArticle.setAuthorName(apAuthor.getName());
        }
        AdChannel adChannel = adChannelServiceI.getById(wmNews.getChannelId());
        if (adChannel != null) {
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }
        apArticle.setLayout(wmNews.getType());
        apArticle.setImages(wmNews.getImages());
        apArticle.setLabels(wmNews.getLabels());
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(new Date());
        apArticle = articleFeign.saveArticle(apArticle);
        return apArticle;
    }


}
